package com.googlecode.hmvc4gwt.example.hmvcblog.service.services.blog.entry;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.blog.Blog;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.blog.BlogEntry;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.user.User;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.IBlogRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.entry.IBlogEntryRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.exceptions.BlogNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.IUserRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.exceptions.UserSessionNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogIdDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryEditDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryNewDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryRemoveDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.exceptions.BlogEntryNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.exceptions.BlogEntryTextEmptyException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.exceptions.BlogEntryTitleEmptyException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.NotBlogOwnerException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.NotLoggedInException;

@Transactional
public class BlogEntryService implements IBlogEntryService {

	private IBlogEntryRepository blogEntryRepository;

	private IBlogRepository blogRepository;

	private IUserRepository userRepository;

	public void addBlogEntry(BlogEntryNewDTO blogEntryNewDTO)
			throws NotLoggedInException, NotBlogOwnerException,
			BlogNotFoundException, BlogEntryTitleEmptyException,
			BlogEntryTextEmptyException {

		try {

			/*
			 * validate the BlogEntryData
			 */
			validateBlogEntryData(blogEntryNewDTO.getTitle(), blogEntryNewDTO
					.getText());

			/*
			 * load current user
			 */
			User user = getUserRepository().findBySessionId(
					blogEntryNewDTO.getSessionId());

			/*
			 * load the Blog
			 */
			Blog blog = getBlogRepository().findById(
					blogEntryNewDTO.getBlogId());

			/*
			 * is the user the owner of the Blog
			 */
			if (user.getId() != blog.getUser().getId()) {
				throw new NotBlogOwnerException();
			}

			/*
			 * convert the BlogEntryNewDTO to a BlogEntry
			 */
			BlogEntry blogEntry = new BlogEntry();
			blogEntry.setBlog(blog);
			blogEntry.setDate(new Date());
			blogEntry.setText(blogEntryNewDTO.getText());
			blogEntry.setTitle(blogEntryNewDTO.getTitle());

			/*
			 * persist the BlogEntry
			 */
			getBlogEntryRepository().addBlogEntry(blogEntry);

		} catch (UserSessionNotFoundException e) {
			throw new NotLoggedInException();
		}

	}

	public void editBlogEntry(BlogEntryEditDTO blogEntryEditDTO)
			throws NotLoggedInException, NotBlogOwnerException,
			BlogEntryTitleEmptyException, BlogEntryTextEmptyException,
			BlogEntryNotFoundException {

		try {

			/*
			 * validate the new BlogEntry data
			 */
			validateBlogEntryData(blogEntryEditDTO.getTitle(), blogEntryEditDTO
					.getText());

			/*
			 * load the current user
			 */
			User user = getUserRepository().findBySessionId(
					blogEntryEditDTO.getSessionId());

			/*
			 * load the edited BlogEntry
			 */
			BlogEntry blogEntry = getBlogEntryRepository().findById(
					blogEntryEditDTO.getBlogEntryId());

			/*
			 * get the Blog of the edited BlogEntry
			 */
			Blog blog = blogEntry.getBlog();

			/*
			 * is the user the owner of the Blog
			 */
			if (user.getId() != blog.getUser().getId()) {
				throw new NotBlogOwnerException();
			}

			/*
			 * update the BlogEntry data
			 */
			blogEntry.setText(blogEntryEditDTO.getText());
			blogEntry.setTitle(blogEntryEditDTO.getTitle());

			/*
			 * persist the changes
			 */
			getBlogEntryRepository().updateBlogEntry(blogEntry);

		} catch (UserSessionNotFoundException e) {

			throw new NotLoggedInException();

		} catch (Exception e) {

			// TODO richtig exception finden
			throw new BlogEntryNotFoundException();
		}

	}

	public IBlogEntryRepository getBlogEntryRepository() {
		return blogEntryRepository;
	}

	public IBlogRepository getBlogRepository() {
		return blogRepository;
	}

	public List<BlogEntryDTO> getListBlogEntries(BlogIdDTO blogIdDTO)
			throws BlogNotFoundException {

		/*
		 * load Blog
		 */
		Blog blog = getBlogRepository().findById(blogIdDTO.getBlogId());
		
		if (blog == null) {
			throw new BlogNotFoundException();
		}

		/*
		 * load all BlogEntries of the Blog
		 */
		List<BlogEntry> listBlogEntry = getBlogEntryRepository()
				.getBlogEntries(blog);

		/*
		 * convert the BlogEntries to BlogEntryDTO's
		 */
		List<BlogEntryDTO> listBlogEntryDTO = new LinkedList<BlogEntryDTO>();
		for (BlogEntry blogEntry : listBlogEntry) {

			BlogEntryDTO blogEntryDTO = new BlogEntryDTO();
			blogEntryDTO.setId(blogEntry.getId());
			blogEntryDTO.setDate(blogEntry.getDate());
			blogEntryDTO.setTitle(blogEntry.getTitle());
			blogEntryDTO.setText(blogEntry.getText());

			listBlogEntryDTO.add(blogEntryDTO);
		}

		return listBlogEntryDTO;
	}

	public IUserRepository getUserRepository() {
		return userRepository;
	}

	public void removeBlogEntry(BlogEntryRemoveDTO blogEntryRemoveDTO)
			throws NotLoggedInException, NotBlogOwnerException {

		try {

			/*
			 * load the current user
			 */
			User user = getUserRepository().findBySessionId(
					blogEntryRemoveDTO.getSessionId());

			/*
			 * load BlogEntry
			 */
			BlogEntry blogEntry = getBlogEntryRepository().findById(
					blogEntryRemoveDTO.getId());

			/*
			 * get Blog of the BlogEntry
			 */
			Blog blog = blogEntry.getBlog();

			/*
			 * is the user the owner of the Blog
			 */
			if (user.getId() != blog.getUser().getId()) {
				throw new NotBlogOwnerException();
			}

			/*
			 * remove BlogEntry
			 */
			getBlogEntryRepository().removeBlogEntry(blogEntry);

		} catch (UserSessionNotFoundException e) {

			throw new NotLoggedInException();

		}
	}

	public void setBlogEntryRepository(IBlogEntryRepository blogEntryRepository) {
		this.blogEntryRepository = blogEntryRepository;
	}

	public void setBlogRepository(IBlogRepository blogRepository) {
		this.blogRepository = blogRepository;
	}

	public void setUserRepository(IUserRepository userRepository) {
		this.userRepository = userRepository;
	}

	private void validateBlogEntryData(String title, String text)
			throws BlogEntryTitleEmptyException, BlogEntryTextEmptyException {

		if ((title == null) || (title.equals(""))) {
			throw new BlogEntryTitleEmptyException();
		}

		if ((text == null) || (text.equals(""))) {
			throw new BlogEntryTextEmptyException();
		}

	}

}
